using ControlCenter.Data;
using ControlCenter.Model;
using ControlCenter.Model.BizEntities;
using MingYuanYun.Context.Abstractions;
using MingYuanYun.Data.Abstractions;
using MingYuanYun.Exception;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ControlCenter.Model.WebApiDto;
using ControlCenter.Operation.Model;
using MingYuanYun.Primitives;

namespace ControlCenter.Operation
{
    /// <summary>
    /// 包信息处理
    /// </summary>
    public class PackageManagementOperation : OperationBase, IPackageManagementOperation
    {
        private readonly IPackageManagementRepository _packageManagementRepository;
        private readonly IPackageConfigRepository _iPackageConfigRepository;

        /// <summary>
        /// 类初始化
        /// </summary>
        /// <param name="context"></param>
        /// <param name="unitOfWork"></param>
        public PackageManagementOperation(IServiceContext context, IUnitOfWork unitOfWork) : base(context, unitOfWork)
        {
            _packageManagementRepository = this.GetRepository<IPackageManagementRepository>();
            _iPackageConfigRepository = this.GetRepository<IPackageConfigRepository>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="projectPackageInfo"></param>
        /// <returns></returns>
        public async Task SavePackageInfo(ProjectPackageInfo projectPackageInfo)
        {
            await _packageManagementRepository.Create(projectPackageInfo);
        }

        #region 机器人的应用
        /// <summary>
        /// 更新机器人的包状态，停用/启用
        /// </summary>
        /// <param name="updatePackageStatusDto"></param>
        /// <returns></returns>
        public async Task<bool> UpdatePackageStatus(UpdatePackageStatusDto updatePackageStatusDto)
        {
            return await _packageManagementRepository.UpdatePackageStatus(updatePackageStatusDto.RobotId, updatePackageStatusDto.packageId, updatePackageStatusDto.packageStatus, updatePackageStatusDto.IsInstall);
        }

        /// <summary>
        /// 获取需要执行的包的信息
        /// </summary>
        /// <param name="robotId"></param>
        /// <returns></returns>
        public async Task<IEnumerable<WaitExecutionPackageDto>> QueryWaitExectionPackage(Guid robotId)
        {
            var packages = await _packageManagementRepository.QueryWaitExectionPackage(robotId);
            
            foreach (var package in packages)
            {
                var configs = await _iPackageConfigRepository.Query(package.PackageId);
                foreach (var config in configs)
                {
                    package.Options.Add(new KeyValuePair<string, string>(config.Name, config.Value));
                }
            }
            return packages;
        }

        /// <summary>
        /// 获取指定的packageInfo
        /// </summary>
        /// <param name="packageId"></param>
        /// <returns></returns>
        public async Task<RobotPackageInfo> Find(Guid packageId)
        {
            return await _packageManagementRepository.Find(packageId);
        }

        /// <summary>
        /// 根据机器人id获取包列表
        /// </summary>
        /// <param name="robotId"></param>
        /// <returns></returns>
        public async Task<IEnumerable<RobotPackageInfo>> QueryPackage(Guid robotId)
        {
            return await _packageManagementRepository.QueryPackage(robotId);
        }

        /// <summary>
        /// 查询所有机器人的应用包概要信息列表
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<RobotPackageShortInfo>> QueryRobotPackageShortInfo()
        {
            return await _packageManagementRepository.QueryRobotPackageShortInfo();
        }

        /// <summary>
        /// 查询机器人的应用包列表
        /// </summary>
        /// <param name="robotId"></param>
        /// <returns></returns>
        public async Task<IEnumerable<SaveRobotPackageInfo>> QuerySaveRobotPackageInfo(Guid robotId)
        {
            return await _packageManagementRepository.QuerySaveRobotPackageInfo(robotId);
        }

        /// <summary>
        /// 更新机器人的包数据
        /// </summary>
        /// <param name="saveDto"></param>
        /// <returns></returns>
        public async Task<bool> UpdateRobotPackageInfo(SaveRobotInfoDto saveDto)
        {
            var robotId = saveDto.RobotInfo.RobotId;
            var oldPackages = await QuerySaveRobotPackageInfo(robotId);

            //处理数据
            var addPackages = saveDto.Packages.Where(p => p.RpId == Guid.Empty).ToList();
            var deletePackages = new List<Guid>();
            oldPackages.ToList().ForEach(old =>
            {
                if (!saveDto.Packages.Select(p => p.RpId).Contains(old.RpId))
                {
                    deletePackages.Add(old.RpId);
                }
            });
            var editPackages = new List<SaveRobotPackageInfo>();
            saveDto.Packages.ForEach(p=>
            {
                if (!(p.RpId == Guid.Empty) && !(deletePackages.Contains(p.RpId)))
                {
                    editPackages.Add(p);
                }
            });

            //数据校验
            ValidateUpdateRobotPackageInfo(saveDto.Packages.Where(p=>!deletePackages.Contains(p.RpId)).ToList());

            //保存数据修改（删除、增加、更新）
            deletePackages.ForEach(p=> _packageManagementRepository.DeleteRobotPackage(p));
            addPackages.ForEach(p=> _packageManagementRepository.AddRobotPackage(p));
            editPackages.ForEach(p=> _packageManagementRepository.UpdateRobotPackageExecCycleInfo(p));

            return true;
        }

        // UpdateRobotPackageInfo参数校验
        private void ValidateUpdateRobotPackageInfo(List<SaveRobotPackageInfo> packages)
        {
            Dictionary<string, List<PackageCounterItem>> cronDict = new Dictionary<string, List<PackageCounterItem>>();
            foreach (var package in packages)
            {
                List<PackageCounterItem> counter = null;
                //字典不存在计数器时添加
                if (!cronDict.TryGetValue(package.ExecCycleCron, out counter))
                {
                    counter = new List<PackageCounterItem>();
                    counter.Add(new PackageCounterItem { Id = package.PackageId, Name = package.PackageName, Count = 1 });
                    cronDict.Add(package.ExecCycleCron, counter);
                    continue;
                }

                var existSamePackage = counter.FirstOrDefault(p => p.Id == package.PackageId);
                //字典存在计数器，计数器中无相同的PackageId时，直接添加到集合
                if (existSamePackage == null)
                {
                    var counterItem = new PackageCounterItem { Id = package.PackageId, Name = package.PackageName, Count = 1 };
                    counter.Add(counterItem);
                    continue;
                }

                //计数器中存在相同的PackageId时，计数器值+1
                existSamePackage.Count += 1;
            }

            //同一个应用同一个频率不允许保存
            cronDict.Values.ForEach(counter =>
            {
                var counterItem = counter.FirstOrDefault(p => p.Count > 1);
                if (counterItem != null)
                {
                    throw new BusinessException($"{counterItem.Name} 存在多个相同执行频率的任务！");
                }
            });
        }

        /// <summary>
        /// 更新机器人应用包的状态
        /// </summary>
        /// <param name="rpId"></param>
        /// <param name="packageStatus"></param>
        /// <param name="oldPackageStatus"></param>
        /// <returns></returns>
        public async Task UpdateRobotPackagePackageStatus(Guid rpId, int packageStatus, int? oldPackageStatus = null)
        {
            await _packageManagementRepository.UpdateRobotPackagePackageStatus(rpId, packageStatus, oldPackageStatus);
        }

        /// <summary>
        /// 删除机器人的应用包
        /// </summary>
        /// <param name="rpId"></param>
        /// <returns></returns>
        public async Task DeleteRobotPackage(Guid rpId)
        {
            await _packageManagementRepository.DeleteRobotPackage(rpId);
        }
        #endregion

        #region 应用包
        /// <summary>
        /// 判断包是否存在
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="version"></param>
        /// <returns></returns>
        public async Task<bool> IsExist(string projectName, string version)
        {
            return await _packageManagementRepository.IsExist(projectName, version);
        }

        /// <summary>
        /// 根据条件查询应用包数据，返回分页数据
        /// </summary>
        /// <param name="paramDto"></param>
        /// <returns></returns>
        public async Task<PagedData<ProjectPackageInfo>> QueryPackageInfo(PackageQueryDto paramDto)
        {
            PagedData<ProjectPackageInfo> pagedData = new PagedData<ProjectPackageInfo>();
            var packages = await _packageManagementRepository.QueryPackageInfo(paramDto.Keywords);
            pagedData.Data = packages.Skip((paramDto.PageIndex - 1) * paramDto.PageSize).Take(paramDto.PageSize).ToList();
            pagedData.TotalCount = packages.Count();
            return pagedData;
        }

        /// <summary>
        /// 根据包ID查询应用包信息
        /// </summary>
        /// <param name="packageId"></param>
        /// <returns></returns>
        public async Task<ProjectPackageInfo> FindPackageInfo(Guid packageId)
        {
            return await _packageManagementRepository.FindPackageInfo(packageId);
        }

        /// <summary>
        /// 根据包名称查询应用包信息
        /// </summary>
        /// <param name="packageName"></param>
        /// <returns></returns>
        public async Task<ProjectPackageInfo> FindPackageInfo(string packageName)
        {
            return await _packageManagementRepository.FindPackageInfo(packageName);
        }

        /// <summary>
        /// 增加一个应用包
        /// </summary>
        /// <param name="packageInfo"></param>
        /// <param name="configItems"></param>
        /// <returns></returns>
        public async Task<bool> InsertPackageInfo(ProjectPackageInfo packageInfo, List<PackageConfigItem> configItems)
        {
            var addPackageRet = await _packageManagementRepository.InsertPackageInfo(packageInfo);
            foreach (var item in configItems)
            {
                await _iPackageConfigRepository.Add(item);
            }
            return addPackageRet;
        }

        /// <summary>
        /// 更新应用包信息
        /// </summary>
        /// <param name="packageInfo"></param>
        /// <param name="configItems"></param>
        /// <returns></returns>
        public async Task<bool> UpdatePackageInfo(ProjectPackageInfo packageInfo, List<PackageConfigItem> configItems)
        {
            var updatePackageRet = await _packageManagementRepository.UpdatePackageInfo(packageInfo);
            foreach (var item in configItems)
            {
                await _iPackageConfigRepository.Add(item);
            }
            return updatePackageRet;
        }

        /// <summary>
        /// 根据包ID删除应用包
        /// </summary>
        /// <param name="packageId"></param>
        /// <returns></returns>
        public async Task<Tuple<bool, string>> DeletePackageInfo(Guid packageId)
        {
            var canDelete = await _packageManagementRepository.CanDeletePackageInfo(packageId);
            if (canDelete)
            {
                var deleteRet = await _packageManagementRepository.DeletePackageInfo(packageId);
                await _iPackageConfigRepository.DeleteByPackageId(packageId);
                return new Tuple<bool, string>(deleteRet, deleteRet ? "删除应用成功！" : "删除应用失败！");
            }
            else
            {
                return new Tuple<bool, string>(false, "此应用已有机器人在使用，不能删除！");
            }
        }
        #endregion

        #region -- 包参数配置 -------------------------------------------------------------------------------------------------------

        /// <summary>
        /// 查询指定应用包的参数配置
        /// </summary>
        /// <param name="packageId">应用包ID</param>
        /// <returns></returns>
        public async Task<IEnumerable<PackageConfigItem>> QueryPackageConfig(Guid packageId)
        {
            return await _iPackageConfigRepository.Query(packageId);
        }

        /// <summary>
        /// 更新应用包的参数配置
        /// </summary>
        /// <param name="packageConfigItems"></param>
        /// <returns></returns>
        public async Task<Tuple<bool, string>> UpdatePackageConfig(List<PackageConfigItem> packageConfigItems)
        {
            using (var scope = CreateScope())
            {
                foreach (var item in packageConfigItems)
                {
                    await scope.GetRepository<IPackageConfigRepository>().Update(item);
                }

                //更新应用包参数配置字段
                Guid packageId = packageConfigItems.FirstOrDefault().PackageId;
                var packageMngRepo = scope.GetRepository<IPackageManagementRepository>();
                var packageInfo = await packageMngRepo.FindPackageInfo(packageId);
                packageInfo.IsCompleteConfig = true;
                await packageMngRepo.UpdatePackageInfo(packageInfo);
            }
            return new Tuple<bool, string>(true, "");
        }
        #endregion
    }
}
